﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Noria.Web.MyMSDN.Models;
using Noria.Web.Utility;
using MmContext = Noria.Web.MyMSDN.Models.MmContext;

namespace Noria.Web.MyMSDN.Workers
{
    internal class MyMSDNWorker : IWorker
    {
        private static readonly log4net.ILog slog = log4net.LogManager.GetLogger("Noria.Spider");
        private static readonly log4net.ILog alog = log4net.LogManager.GetLogger("Noria.Audit");

        private static readonly string rootUrl = (string)NConfig.Root.spider.settings.mymsdn;

        private readonly IStatistics stat;
        private readonly AsyncWaiter waiter;

        private MyMSDNWorker(IStatistics stat, AsyncWaiter waiter)
        {
            this.stat = stat;
            this.waiter = waiter;
        }

        public static IWorker Create(IStatistics stat, AsyncWaiter waiter)
        {
            return new MyMSDNWorker(stat, waiter);
        }

        public void Work()
        {
            Download();
        }

        // download checksum data from mymsdn.info
        private void Download()
        {
            dynamic s = HttpBot.RequestJArray(stat, rootUrl + "/archive.ashx", null, null,
                new Dictionary<string, string> { { "NAuth", CreateIdentityToken() } });
            slog.InfoFormat("Retrieve checksum info from mymsdn.info, count={0}", (int)s.Count);

            // insert into checksum
            using (var db = new MmContext())
            {
                foreach (dynamic entity in s)
                {
                    db.Checksum.Add(new Checksum()
                        {
                            eMule = entity.eMule,
                            FileName = entity.FileName,
                            Sha1 = entity.Sha1,
                            Size = entity.Size,

                            Initiator = "mm",
                            SubmittedDate = DateTime.Now
                        });
                }

                int ret = db.SaveChanges();
                alog.InfoFormat("Checksum updated, count={0}", ret);
            }
        }

        // upload new data to mymsdn.info
        public void Upload()
        {
            byte[] binary = null;

            // insert into checksum
            using (var db = new MmContext())
            {
                var data = db.Categories.Include("Families.Files").ToArray();
                var raw = JArray.FromObject(data).ToString(Formatting.None);
                binary = GZipHelper.Compress(raw);
            }

            HttpBot.RequestNonQuery(stat, rootUrl + "/upload2.ashx", binary, null,
                new Dictionary<string, string> { { "NAuth", CreateIdentityToken() } });
            slog.Info("Uplaod new data to mymsdn.info");
        }

        private static string CreateIdentityToken()
        {
            string user = NConfig.Root.identity.user;
            string code = NConfig.Root.identity.code;
            var buffer = Encoding.UTF8.GetBytes(user + ":" + code);
            var passcode = "Noria " + Convert.ToBase64String(buffer);
            return passcode;
        }
    }
}